iT邦幫忙

2022 iThome 鐵人賽

DAY 11
1
Software Development

C# ASP.NET MVC實作: 30天打造屬於你的網站應用程式系列 第 11

(DAY 11)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-簡易CRUD

  • 分享至 

  • xImage
  •  

● CRUD是什麼?

CRUD分別代表的是:Create(建立、新增)、Read(讀取、查詢)、Update(更新、改正)、Delete(刪除),這4個動作就是在操作資料庫程式的時候最基本會用到的四項作業,中文一般稱作「增刪查改」。

CRUD對照到SQL語法和HTTP請求方法如下表格:

操作 SQL HTTP
Create INSERT POST/PUT
Read SELECT GET
Update UPDATE POST/PUT/PATCH
Delete DELETE POST/DELETE

關於更詳細的說明可以參考下列連結:
https://zh.wikipedia.org/zh-tw/%E5%A2%9E%E5%88%AA%E6%9F%A5%E6%94%B9

接著我們延續昨天使用Enitity Framework建立的資料庫內容,來示範如何達成CRUD各動作,同時也先在要實作網站專案之前,做個小小的統整練習。

● 範例-Read

我們先從目前最熟悉的Read開始,以使用者操作流程來說就是針對篩選的條件讀取資料,並顯示於畫面上。這部分我們練習過不少次了,參考步驟如下:

  1. ShoppingController內新增Read()動作方法,目的是將所有會員資料顯示於清單,另外這邊刻意使用OrderByDescending讓資料依照UserId以降冪方式排序,Code如下:
        public ActionResult Read()
        {
            var db = new dbShoppingEntities();
            var members = db.Member.OrderByDescending(m=>m.UserId).ToList();
            return View(members);
        }
  1. 接著新增Read()的檢視頁面,這次我們試著使用快速的方式建立現成View,首先一樣先新增檢視,在加入時依照下圖選取「List」範本,並使用模型類別為「Member」,完成後按下「加入」。

    ※這邊有可能會發生EntityFramework相容問題,解決方式是將繁體中文套件解除安裝,可參考下圖處理。


  2. 移到檢視頁面會發現開發工具已經自動產生簡易的View,Code如下:

@model IEnumerable<DemoEntityFramework.Models.Member>

@{
    ViewBag.Title = "Read";
}

<h2>Read</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.UserId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Password)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.UserName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Email)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Address)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.UserId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Password)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.UserName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Email)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Address)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table>

  1. 將頁面執行起來如下圖,會員資料也確實有按照UserId降冪排序。

● 範例-Create

接著說明新增資料的方式,首先在Read的檢視會看到資料列表上方有個Create New的連結,我們希望User按下這個連結後可以進入新增資料的頁面,另外從View的程式碼會看到ActionLink預設的動作方法名稱為「Create」。

建立步驟如下:

  1. 先新增Create()方法,並新增對應的View,這次加入View時依照下圖選取「Create」範本,並使用模型類別為「Member」,完成後按下「加入」。
       public ActionResult Create()
        {
            return View();
        }

  1. 產生的Code會如下方一樣,這邊我們會看到一些之前沒講到的HTML Helper方法,我們暫時先忽略,先將畫面執行起來看看。
@model DemoEntityFramework.Models.Member

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Member</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.UserId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserId, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

  1. 執行畫面如下,可以看到一個簡單的新增表單已經建立好了,左下方的Back to List連結,預設會連到Index,這邊我們將它改成Read,以便可以回到原本查詢會員的頁面。

  2. 再來我們來處理在表單按下Submit鍵的動作,表單預設是使用HTTP POST請求 & 與檢視同名的Create()動作方法,送出表單後會導回至Read頁面檢視新增後的內容,所以在Controller底下再新增如下Code:

        [HttpPost]
        public ActionResult Create(Member member)
        {
            var db = new dbShoppingEntities();
            db.Member.Add(member);
            db.SaveChanges();

            return RedirectToAction("Read");
        }
  • 這邊要注意的是使用Add()方法新增資料後,必須使用SaveChanges()方法才會將變更的內容儲存,同理在做Edit與Delete的時候也一樣。
  1. 將Create檢視頁面執行實測看看,隨意新增一筆資料後按下Create按鈕,如果導回Read頁面有顯示資料就是成功囉~

● 範例-Update

在Read頁面每一筆資料後面都有Edit連結,我們希望點進去後可以修改資料內容,並且按下儲存後會回到Read頁面以檢視變更後結果。

首先看看Edit這個ActionLink是怎麼寫的,如下圖可以發現它會導向名為Edit的動作方法,且後面會帶一個路由值是該筆資料的Id。(路由的規範可以回頭看看DAY 3~)

在Member資料表內的Id欄位是屬於主索引鍵,主索引鍵必須是唯一值且不可為NULL,一張資料表內只會有一個主索引鍵,概念可以想成是不會重複的流水編號,因此通常用作為網址的路由值。

當我們將滑鼠移至Edit連結的上方,可以看到瀏覽器下方顯示的網址為https://localhostXXXXX/Shoppong/Edit/{id},等同於https://localhostXXXXX/Shoppong/Edit?id={id},是否有印象在DAY 3時我們也看過類似的範例呢?

因此作法如下:

  1. 新增Edit()動作方法,並將參數id放入其中,透過LINQ查詢Member物件中符合該唯一id的資料,將它當作model傳入View使用,參考下方Code:
        public ActionResult Edit(int id)
        {
            var db = new dbShoppingEntities();
            var member = db.Member.Where(m => m.Id == id).FirstOrDefault();
            //也可寫成下面
            //var member = db.Member.FirstOrDefault(m => m.Id == id);
            return View(member);
        }
  1. 接著撰寫View的部分,加入View時依照下圖選取「Edit」範本,並使用模型類別為「Member」,完成後按下「加入」。

  2. 產生的Code如下,一樣將左下方的Back to List連結改成Read,以便可以回到原本的頁面。

@model DemoEntityFramework.Models.Member

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Member</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.UserId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserId, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.UserName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Read")
</div>

  1. 將頁面執行起來後畫面如下,可以看到呈現方式一樣是個表單,但透過將model傳入view,原本的資料內容會被帶進來。

  2. 再來就是按下表單送出的部分啦~同樣是要寫個POST方法,並導回Read頁面。修改的原理也很好懂,利用Id條件判斷取得資料庫內該筆資料,然後將修改送出後的物件屬性一一賦值回該筆資料,最後記得使用SaveChanges()儲存變更,Code如下:

        [HttpPost]
        public ActionResult Edit(Member member)
        {
            var db = new dbShoppingEntities();
            var memberData = db.Member.Where(m => m.Id == member.Id).FirstOrDefault();
            memberData.UserId = member.UserId;
            memberData.UserName = member.UserName;
            memberData.Password = member.Password;
            memberData.Email = member.Email;
            memberData.Address = member.Address;
            db.SaveChanges();

            return RedirectToAction("Read");
        }
  1. 進入Read頁面後試著編輯任意資料,看看是否能修改成功。

● 範例-Delete

刪除單筆資料的道理和Edit做法很像,差別是在於取得資料後就直接把該筆資料移除了。另外刪除前我們希望先顯示要刪除的資料內容,可以讓User有個確認和反悔的機會。

因此一樣先建立Delete()動作方法,加入id參數。

        public ActionResult Delete(int id)
        {
            var db = new dbShoppingEntities();
            var member = db.Member.Where(m => m.Id == id).FirstOrDefault();
            return View(member);
        }

接著新增View,範本改選擇「Delete」。

View Code如下,一樣將左下方的Back to List連結改成Read,以便可以回到原本的頁面。

@model DemoEntityFramework.Models.Member

@{
    ViewBag.Title = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>Member</h4>
    <hr />

    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.UserId)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.UserId)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Password)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Password)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.UserName)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.UserName)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Email)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Email)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Address)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Address)
        </dd>

    </dl>

    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-actions no-color">
            <input type="submit" value="Delete" class="btn btn-default" /> |
            @Html.ActionLink("Back to List", "Read")
        </div>
    }
</div>

View執行畫面如下:

最後就是刪除的POST方法,使用Remove()來移除選擇的資料,並執行SaveChange(),Code如下:

        [HttpPost]
        public ActionResult Delete(Member member)
        {
            var db = new dbShoppingEntities();
            var memberData = db.Member.Where(m => m.Id == member.Id).FirstOrDefault();
            db.Member.Remove(memberData);
            db.SaveChanges();

            return RedirectToAction("Read");
        }

完成後就可以實際來測試看看是否能確實刪除資料囉~

● 小結

今天介紹了基本CRUD方法,利用Entity Framework簡單操作資料庫內容,並且透過內建的範本快速建立檢視頁面。前面這10天相信大家對MVC互動的方式愈來愈熟悉了,接下來的幾天就要來實作一個小型的網站專案囉~那就明天見啦!

※小弟不才,在軟體的世界還只是個小菜雞,如果內容有任何謬誤或問題,還請各位大神前輩們多多批評指教~歡迎下方留言討論^^


上一篇
(DAY 10)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-使用 Entity Framework 存取與操作資料庫
下一篇
(DAY 12)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-授權過濾器驗證
系列文
C# ASP.NET MVC實作: 30天打造屬於你的網站應用程式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言